from fastapi import APIRouter, Request, Form, status, Response as FastAPIResponse, Body
from fastapi.responses import JSONResponse
from models import COLLECTION_NAMES
from models.db import get_mongo_db, get_redis_client, redis_client
from schemas import User
from utils.password_encryption import password_hash, verify_password
from utils.jwt_util import encode_token, decode_token, verify_token, should_refresh_token
from utils.response import Response
import re
import json
from bson import ObjectId

# schemas导入暂时保留，但先不修改现有代码逻辑
# from schemas import UserLogin, UserCreate, Token, DataResponse, ErrorResponse

router = APIRouter(prefix="/api/auth", tags=["认证"])

# 添加create_access_token函数
def create_access_token(data: dict):
    """创建访问令牌"""
    return encode_token(data)

@router.post("/login")
async def login(email: str = Body(...), password: str = Body(...)):
    """用户登录API"""
    # 获取数据库连接实例
    mongo_db = get_mongo_db()
    redis_client = get_redis_client()

    # 使用邮箱查找用户
    user = mongo_db[COLLECTION_NAMES["users"]].find_one({"email": email})
    if not user:
        return Response.error(
            code=status.HTTP_401_UNAUTHORIZED,
            message="邮箱或密码错误"
        )

    # 验证密码
    if not verify_password(password, user["password"]):
        return Response.error(
            code=status.HTTP_401_UNAUTHORIZED,
            message="邮箱或密码错误"
        )

    # 创建访问令牌
    access_token = create_access_token(
        data={"sub": str(user["_id"]), "username": user["username"], "email": user["email"]}
    )

    # 获取token的payload以获取token_id
    payload = verify_token(access_token)
    if payload:
        token_id = payload.get("token_id")
        # 将token存储到Redis中，key为user:user_id:tokens，value为token_id和token的映射
        # 设置过期时间为1天
        redis_key = f"user:{str(user['_id'])}:tokens"
        token_data = {
            "token": access_token,
            "created_at": "now()",
            "expires_at": "now() + 86400"
        }
        redis_client.hset(redis_key, token_id, json.dumps(token_data))
        redis_client.expire(redis_key, 86400)  # 1天过期

    # 返回JSON响应
    return Response.success(
        data={
            "access_token": access_token,
            "token_type": "bearer",
            "user": {
                "id": str(user["_id"]),
                "username": user["username"],
                "email": user["email"]
            }
        }
    )

@router.post("/register")
async def register(
        username: str = Body(...),
        password: str = Body(...),
        confirm_password: str = Body(...),
        email: str = Body(...)
):
    """用户注册API"""
    # 获取数据库连接实例
    mongo_db = get_mongo_db()

    # 验证密码是否一致
    if password != confirm_password:
        return Response.error(
            code=status.HTTP_400_BAD_REQUEST,
            message="两次输入的密码不一致"
        )

    # 验证用户名格式
    if not re.match(r'^[a-zA-Z0-9_]{3,20}$', username):
        return Response.error(
            code=status.HTTP_400_BAD_REQUEST,
            message="用户名必须是3-20位字母、数字或下划线"
        )

    # 验证邮箱格式
    if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
        return Response.error(
            code=status.HTTP_400_BAD_REQUEST,
            message="邮箱格式不正确"
        )

    # 检查邮箱是否已存在（邮箱是唯一的）
    existing_email = mongo_db[COLLECTION_NAMES["users"]].find_one({"email": email})
    if existing_email:
        return Response.error(
            code=status.HTTP_400_BAD_REQUEST,
            message="邮箱已被注册"
        )

    # 创建用户数据
    hashed_password = password_hash(password)
    user_data = {
        "username": username,
        "password": hashed_password,
        "email": email,
        "is_admin": False,
        "created_at": "now()",
        "updated_at": "now()"
    }

    # 插入用户数据
    result = mongo_db[COLLECTION_NAMES["users"]].insert_one(user_data)

    # 创建响应
    if result.inserted_id:
        return Response.success(
            code=status.HTTP_201_CREATED,
            message="注册成功",
            data={
                "user_id": str(result.inserted_id),
                "username": username,
                "email": email
            }
        )
    else:
        return Response.error(
            code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="注册失败，请稍后重试"
        )


@router.post("/logout")
async def logout(request: Request):
    """用户登出"""
    # 获取Redis连接实例
    redis_client = get_redis_client()

    # 从请求头获取token
    auth_header = request.headers.get("Authorization")
    if auth_header and auth_header.startswith("Bearer "):
        token = auth_header.split(" ")[1]
        # 验证token并获取payload
        payload = verify_token(token)
        if payload:
            user_id = payload.get("sub")
            token_id = payload.get("token_id")
            if user_id and token_id:
                # 从Redis中删除token
                redis_key = f"user:{user_id}:tokens"
                await redis_client.hdel(redis_key, token_id)

                # 如果该用户没有其他token了，删除整个key
                if redis_client.hlen(redis_key) == 0:
                    await redis_client.delete(redis_key)

    # 返回成功响应
    return Response.success(message="登出成功")


@router.post("/refresh-token")
async def refresh_token(request: Request):
    """刷新token"""
    # 从请求头获取token
    auth_header = request.headers.get("Authorization")
    if not auth_header or not auth_header.startswith("Bearer "):
        return Response.error(
            code=status.HTTP_401_UNAUTHORIZED,
            message="未授权访问"
        )

    old_token = auth_header.split(" ")[1]
    # 验证token并获取payload
    payload = verify_token(old_token)
    if not payload:
        return Response.error(
            code=status.HTTP_401_UNAUTHORIZED,
            message="无效的token"
        )

    # 检查token是否在Redis中
    user_id = payload.get("sub")
    token_id = payload.get("token_id")
    if not user_id or not token_id:
        return Response.error(
            code=status.HTTP_401_UNAUTHORIZED,
            message="无效的token格式"
        )

    redis_key = f"user:{user_id}:tokens"
    token_data_str = redis_client.hget(redis_key, token_id)
    if not token_data_str:
        return Response.error(
            code=status.HTTP_401_UNAUTHORIZED,
            message="token已过期或已被撤销"
        )

    # 创建新的token
    new_token = create_access_token(
        data={
            "sub": user_id,
            "username": payload.get("username"),
            "email": payload.get("email")
        }
    )

    # 获取新token的token_id
    new_payload = verify_token(new_token)
    if new_payload:
        new_token_id = new_payload.get("token_id")
        # 存储新token到Redis
        new_token_data = {
            "token": new_token,
            "created_at": "now()",
            "expires_at": "now() + 86400"
        }
        await redis_client.hset(redis_key, new_token_id, json.dumps(new_token_data))
        await redis_client.expire(redis_key, 86400)  # 1天过期

        # 删除旧token
        await redis_client.hdel(redis_key, token_id)

    return Response.success(
        data={
            "access_token": new_token,
            "token_type": "bearer"
        }
    )
